package com.jweb.framework.security.data.transform;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.multipart.MultipartFile;

import com.jweb.framework.core.Context;
import com.jweb.framework.core.CoreException;
import com.jweb.framework.core.CoreRuntimeException;
import com.jweb.framework.core.Interceptor;
import com.jweb.framework.security.data.safe.DataFieldDecrypt;
import com.jweb.framework.security.data.safe.DataFieldEncrypt;
import com.jweb.framework.security.data.safe.IDecrypt;
import com.jweb.framework.security.data.safe.IEncrypt;
import com.jweb.framework.security.pass.IDecryptPass;

/**
 * 修改人： Thomas
 * 修改内容：新增 
 * 类说明：对部分需要加/解密的数据库字段加/解密处理
 */
public class DataTransformInterceptor implements Interceptor , InitializingBean , ApplicationContextAware {
	
	private boolean securityFlag = false ;
	private ApplicationContext context ;
	private String passwd ;
	private String securityId = "DATA001" ;
	private String fileDeKey = "cem_storage_outputStream";
	
	private static Logger logger = LoggerFactory.getLogger(DataTransformInterceptor.class);
	private Map<String, String> dataMap ;
	
	private IEncrypt encrypt ;
	private IDecrypt decrypt ;
	
	public void setSecurityFlag(boolean securityFlag){
		this.securityFlag = securityFlag ;
	}
	
	public void setFileDeKey(String fileDeKey){
		this.fileDeKey = fileDeKey ;
	}
	
	public void setSecurityId(String id){
		this.securityId = id ;
	}
	
	@Override
	public void setApplicationContext(ApplicationContext applicationContext)
			throws BeansException {
		this.context = applicationContext ;
	}

	@Override
	public void onRequest(Context context) throws CoreException,CoreRuntimeException {
		// 加密处理
		if(this.securityFlag){
			Map<String , Object> reqMap = context.getDataMap();
			Set<String> keySet = reqMap.keySet();
			Iterator<String> it = keySet.iterator() ;
			while(it.hasNext()){
				String key = it.next();
				if(this.dataMap.containsKey(key)){
					if(reqMap.get(key) instanceof String){
						String value = (String) reqMap.get(key);
						String securityData = this.encrypt.getEncryptStr(value, this.passwd);
						context.setData(key, securityData);
					}
					// 对文件的处理
					else if(reqMap.get(key) instanceof MultipartFile){
						MultipartFile file = (MultipartFile) reqMap.get(key);
						try {
							InputStream is = file.getInputStream() ;
							int len = is.available() ;
							byte[] bytes = new byte[len];
							is.read(bytes);
							is.close();
							
							byte[] storage_file_content = this.encrypt.getEncryptBytes(bytes , this.passwd);
							context.setData(key+"_content", storage_file_content);
						} catch (IOException e) {
							e.printStackTrace();
							throw new CoreException("JAVACO1001", "file encrypt fail.") ;
						}
					}
				}
			}
		}
	}

	@Override
	public void onResponse(Context context, Throwable throwable) {
		if(throwable != null){
			return ;
		}
		// 解密处理
		if(this.securityFlag){
			Map<String , Object> respMap = context.getDataMap();
			Set<String> keySet = respMap.keySet();
			Iterator<String> it = keySet.iterator();
			while(it.hasNext()){
				String key = it.next();
				if(this.dataMap.containsKey(key)){
					if(respMap.get(key) instanceof String){
						String securityData = (String) respMap.get(key);
						try {
							String data = this.decrypt.getData(securityData , this.passwd);
							context.setData(key , data);
						} catch (UnsupportedEncodingException e) {
							e.printStackTrace();  // 此地需要如何处理？？？？？？？？？？？？？？
							return ;
						}
					}
					else if(respMap.get(this.fileDeKey) instanceof byte[]){
						byte[] storage_file_content = context.getData(this.fileDeKey);
						byte[] deBytes = this.decrypt.getData(storage_file_content , this.passwd);
						context.setData("outputStream", deBytes);
					}
				}
			}
		}
	}
	
	@Override
	public void afterPropertiesSet() throws Exception {
		try {
			Properties pro = new Properties();
			pro.load(this.getClass().getClassLoader().getResourceAsStream("properties/dataencrypt.properties"));
			this.dataMap = new LinkedHashMap<String, String>((Map)pro);
			
			JdbcTemplate jdbcTemplate = (JdbcTemplate) context.getBean("jdbcTemplate");
			IDecryptPass idecryptpass = DataPwdPassFac.getDecryptPass();
			this.passwd = idecryptpass.getDePass(jdbcTemplate , securityId);
		} catch (Exception e) {
			e.printStackTrace() ;
		}
		if(this.encrypt == null){
			this.encrypt = new DataFieldEncrypt();
		}
		if(this.decrypt == null){
			this.decrypt = new DataFieldDecrypt();
		}
	}

	

}
